#include "StdAfx.h"

#include <PSDFCore/Thread/PosixThreads.h>

//-----------------------------------
// PosixThread
//-----------------------------------

PosixThread::PosixThread(void)
{
}

PosixThread::~PosixThread(void)
{
}

void PosixThread::start()
{
	pthread_attr_t attr;

	pthread_attr_init( &attr );

	pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE );

	pthread_create( &_threadId, &attr, threadFunc, ( void * )this );

	pthread_attr_destroy( &attr );
}

void PosixThread::stop()
{
	pthread_kill(_threadId, 0);
}

pthread_t PosixThread::getThreadId()
{
	return _threadId;
}

void * PosixThread::threadFunc( void * instance )
{
	PosixThread * _instance = ( PosixThread * )instance;

	_instance->run();

	pthread_exit( NULL );

	return NULL;
}

void PosixThread::waitUntilDone(pthread_t threadId)
{
	pthread_join( threadId, NULL );	
}

void PosixThread::msleep(long millisec)
{
#ifdef _WIN32
	Sleep(millisec);
#else
	usleep(millisec * 1000);
#endif
}


//-----------------------------------
// PosixMutex
//-----------------------------------

PosixMutex::PosixMutex()
{
	pthread_mutex_init( &_mutex, NULL );
}

PosixMutex::~PosixMutex()
{
	pthread_mutex_destroy( &_mutex );
}

void PosixMutex::lock()
{
	pthread_mutex_lock( &_mutex );
}

void PosixMutex::unlock()
{
	pthread_mutex_unlock( &_mutex );
}

bool PosixMutex::tryLock()
{
	return ( 0 == pthread_mutex_trylock( &_mutex ) );
}


//-----------------------------------
// PosixSemaphore
//-----------------------------------
PosixSemaphore::PosixSemaphore( int initCount )
{
	sem_init( &_sem, 0, initCount );
}

PosixSemaphore::~PosixSemaphore()
{
	sem_destroy( &_sem );
}

void PosixSemaphore::acquire()
{
	sem_wait( &_sem );
}

void PosixSemaphore::release( unsigned int n )
{
	if( n == 0 )
	{
		return;
	}
	if( n == 1 )
	{
		sem_post( &_sem );
	}
	else
	{
		sem_post_multiple( &_sem, n );
	}
}

bool PosixSemaphore::tryAcquire()
{
	return ( 0 == sem_trywait( &_sem ) );
}

//-------------------------------------
// PosixReadWriteLock
//-------------------------------------

PosixReadWriteLock::PosixReadWriteLock()
{
	pthread_rwlock_init( &_rwlock, NULL );
}

PosixReadWriteLock::~PosixReadWriteLock()
{
	pthread_rwlock_destroy( &_rwlock );
}

void PosixReadWriteLock::lockForRead()
{
	pthread_rwlock_rdlock( &_rwlock );
}

void PosixReadWriteLock::lockForWrite()
{
	pthread_rwlock_wrlock( &_rwlock );
}

bool PosixReadWriteLock::tryLockForRead()
{
	return ( 0 == pthread_rwlock_tryrdlock( &_rwlock ) );
}

bool PosixReadWriteLock::tryLockForWrite()
{
	return ( 0 == pthread_rwlock_trywrlock( &_rwlock ) );
}

void PosixReadWriteLock::unlock()
{
	pthread_rwlock_unlock( &_rwlock );
}
